#!/usr/bin/env python
import pygtk
pygtk.require('2.0')
import gtk
import random
import pygame

# Start game music!
pygame.init()
sound = pygame.mixer.Sound('sounds/background_music.wav')
sound.play(100, 0)

def quitGame(w):
    w.destroy()

# This is a callback function, which we later will connect
# to the clicked signal of the button, which will be triggered
# when the user clicks the button with a mouse.
def on_button_clicked(button):
    for i in range(0, number_unknowns):
        if(scales[i].get_value() != variable_dictionary[used_variables[i]]):
            doh_sound = pygame.mixer.Sound('sounds/doh.wav')
            doh_sound.play()
            break
        else:
            if (i == number_unknowns - 1):
                clapping = pygame.mixer.Sound('sounds/clapping.wav')
                clapping.play()


# the help/about screen
def helpmenu(s):
    window = gtk.Window()
    notebook = gtk.Notebook()
    notebook.set_tab_pos(gtk.POS_LEFT)
    banner = gtk.Image()
    banner.set_from_file("graphics/banner.png")
    aboutframe = gtk.Frame()
    abouttext = gtk.Label("Produce Puzzle was created by Elizabeth Deng, Matthew Michihara, and Aaron Macris. It was coded in python using pygtk and pygame libraries. Fruit images were created in Adobe Photoshop CS. It was created specifically for the OLPC project in a code-a-thon at University of Southern California.")
    abouttext.set_line_wrap(True)
    aboutbox = gtk.VBox(False, 0)
    aboutbox.pack_start(addBuffer(), False, False, 0)
    aboutbox.pack_start(banner, False, False, 0)
    aboutbox.pack_start(addBuffer(), False, False, 0)
    aboutbox.pack_start(abouttext, False, False, 0)
    aboutframe.add(aboutbox)
    helpframe = gtk.Frame()
    helptext = gtk.Label("This puzzle is simple. Each type of fruit has a value. The pieces of fruit are organized so that the values of each piece of fruit in a row is added, and that sum is displayed at the right. ")
    helptext2 = gtk.Label("The sums of all the pieces of fruit in a column are displayed at the bottom. In order to solve the puzzle, you must find the value of each type of fruit.")
    helptext3 = gtk.Label("To input the values of the fruit, you must slide the bars that appear below the fruit menu at the bottom of the screen.")
    helptext4 = gtk.Label("You may start a new game with a larger grid by selecting 'new game' from the top of the screen and selecting a grid size. When you create a new game, the previous game will exit.")
    helptext6 = gtk.Label("When you have input all the values that you think are correct, you can click the 'check' button to verify. If you are wrong, you will hear an unpleasant 'doh' sound. If you are correct, you will hear applause. ")
    helptext.set_line_wrap(True)
    helptext2.set_line_wrap(True)
    helptext3.set_line_wrap(True)
    helptext4.set_line_wrap(True)
    helptext6.set_line_wrap(True)
    helpbox = gtk.VBox(False, 10)
    helpbox.pack_start(addBuffer(), False, False, 0)
    helpbox.pack_start(helptext, False, False, 0)
    helpbox.pack_start(helptext2, False, False, 0)
    helpbox.pack_start(helptext3, False, False, 0)
    helpbox.pack_start(helptext4, False, False, 0)
    helpbox.pack_start(helptext6, False, False, 0)
    helpbox.pack_start(addBuffer(), False, False, 0)
    helpframe.add(helpbox)
    notebook.append_page(aboutframe, gtk.Label("About"))
    notebook.append_page(helpframe, gtk.Label("Instructions"))
    # the menu!
    menu1 = gtk.Menu()    # Don't need to show menus
    
    quitgame = gtk.MenuItem("Quit")

    # Add them to the menu
    menu1.append(quitgame)
    
    # Attach the callback functions to the activate signal
    quitgame.connect_object("activate", quitGame, window)
    
    quitgame.show()
    
    menu_bar = gtk.MenuBar()

    menuitem1 = gtk.MenuItem("Quit")
    menuitem1.set_submenu(menu1)
    menu_bar.append(menuitem1)
    mainbox = gtk.VBox(False, 0)
    mainbox.pack_start(menu_bar, False, False, 0)
    mainbox.pack_start(notebook, False, False, 0)
    window.add(mainbox)
    window.show_all()
    #window.connect("delete-event", gtk.main_quit)
        
# a label buffer
def addBuffer():
    buffer = gtk.Label("  ")
    return buffer

# adding images
def addApple():
    imgApple = gtk.Image()
    imgApple.set_from_file("graphics/apple.png")
    return imgApple

def addOrange():
    imgOrange = gtk.Image()
    imgOrange.set_from_file("graphics/orange.png")
    return imgOrange

def addBanana():
    imgBanana = gtk.Image()
    imgBanana.set_from_file("graphics/bananas.png")
    return imgBanana

def addPlum():
    imgPlum = gtk.Image()
    imgPlum.set_from_file("graphics/plum.png")
    return imgPlum

def addPear():
    imgPear = gtk.Image()
    imgPear.set_from_file("graphics/pear.png")
    return imgPear

def addMango():
    imgMango = gtk.Image()
    imgMango.set_from_file("graphics/mango.png")
    return imgMango

def addStrawberry():
    imgStrawberry = gtk.Image()
    imgStrawberry.set_from_file("graphics/strawberry.png")
    return imgStrawberry

def addKiwi():
    imgKiwi = gtk.Image()
    imgKiwi.set_from_file("graphics/kiwi.png")
    return imgKiwi

def addWatermelon():
    imgWatermelon = gtk.Image()
    imgWatermelon.set_from_file("graphics/watermelon.png")
    return imgWatermelon

def mainGame(i):

    # base game start
    # Lower and upper bound of the random generator.
    lower_bound = 1
    upper_bound = 20
    
    # Number of unknowns.
    number_unknowns = i


    
    # Dictionary of variable names.
    alphabet_dictionary = {0:'a', 1:'b', 2:'c', 3:'d', 4:'e',
                       5:'f', 6:'g', 7:'h', 8:'i'}
    


    # Declare arrays to create grid array.
    grid = []
    row = []
    
    # Declare row and column sum arrays.
    row_sum = []
    column_sum = []
    
    # Declare array holding algebra game grid.
    for i in range(0, number_unknowns):
        for j in range(0, number_unknowns):
            row.append(0)
        grid.append(row)
        row = []

# clear out variable_dictionary and used_variables
    while (used_variables):
        used_variables.pop()

    while (variable_dictionary):
        variable_dictionary.clear()

# Load variable dictionary with a variable name as the key, mapped to a random integer.
    for i in range(0, number_unknowns):
        done = False
        while not done:
            done = True
            random_variable = alphabet_dictionary[random.randint(0, len(alphabet_dictionary) - 1)]
            if variable_dictionary.has_key(random_variable):
                done = False

        done = False
        while not done:
            done = True
            random_number = random.randint(lower_bound, upper_bound)
            for value in variable_dictionary.itervalues():
                if value == random_number:
                    done = False
        
        variable_dictionary[random_variable] = random_number
        used_variables.append(random_variable)
    used_variables.sort()

    # Load the algebra grid with random variables
    for i in range(0, number_unknowns):
        for j in range(0, number_unknowns):
            random_select = random.randint(0, number_unknowns - 1)
            grid[i][j] = used_variables[random_select]

    # Get row sums.
    for i in range(0, number_unknowns):
        temp_sum = 0
        for j in range(0, number_unknowns):
            temp_sum = temp_sum + variable_dictionary[grid[i][j]]
        row_sum.append(temp_sum)

    # Get column sums.
    for i in range(0, number_unknowns):
        temp_sum = 0
        for j in range(0, number_unknowns):
            temp_sum = temp_sum + variable_dictionary[grid[j][i]]
        column_sum.append(temp_sum)
    # base game end

    # DEBUG
    print "grid " + str(grid)
    print "variable dictionary " + str(variable_dictionary)
    print "row sum " + str(row_sum)
    print "column sum " + str(column_sum)

    
    # Create a new window
    window = gtk.Window()
    
    def setNum(i):
        window.destroy()
        mainGame(i)

    # the menu!
    menu1 = gtk.Menu()    # Don't need to show menus
    menu2 = gtk.Menu()
    menu3 = gtk.Menu()
    
    # Create the menu items
    three = gtk.MenuItem("3x3")
    four = gtk.MenuItem("4x4")
    five = gtk.MenuItem("5x5")
    six = gtk.MenuItem("6x6")
    seven = gtk.MenuItem("7x7")
    eight = gtk.MenuItem("8x8")
    nine = gtk.MenuItem("9x9")
    helpme = gtk.MenuItem("Help")
    quitgame = gtk.MenuItem("Quit")

    # Add them to the menu
    menu1.append(three)
    menu1.append(four)
    menu1.append(five)
    menu1.append(six)
    menu1.append(seven)
    menu1.append(eight)
    menu1.append(nine)
    menu2.append(quitgame)
    menu3.append(helpme)
    
    # Attach the callback functions to the activate signal
    three.connect_object("activate", setNum, 3)
    four.connect_object("activate", setNum, 4)
    five.connect_object("activate", setNum, 5)
    six.connect_object("activate", setNum, 6)
    seven.connect_object("activate", setNum, 7)
    eight.connect_object("activate", setNum, 8)
    nine.connect_object("activate", setNum, 9)
    quitgame.connect_object("activate", quitGame, window)
    helpme.connect_object("activate", helpmenu, " ")    
    
    # We do need to show menu items
    three.show()
    four.show()
    five.show()
    six.show()
    seven.show()
    eight.show()
    nine.show()
    helpme.show()
    quitgame.show()
    
    menu_bar = gtk.MenuBar()

    menuitem1 = gtk.MenuItem("New Game")
    menuitem2 = gtk.MenuItem("Quit")
    menuitem3 = gtk.MenuItem("Help")
    menuitem1.set_submenu(menu1)
    menuitem2.set_submenu(menu2)
    menuitem3.set_submenu(menu3)
    menu_bar.append(menuitem1)
    menu_bar.append(menuitem2)
    menu_bar.append(menuitem3)


    # Here we connect the "delete-event" event to a signal handler.
    # This event occurs when we the user closes window,
    # We connect it to gtk.main_quit, so it quits the main loop
    # and the program terminates
    window.connect("delete-event", gtk.main_quit)
    window.connect("destroy", gtk.main_quit)
    
    # Sets the border width of the window. length depends
    # on what's in the pack box
    window.set_border_width(0)

    # Creates the button to check answers
    button1 = gtk.Button("Check!")
    
    # When the button receives the "clicked" signal, it will call the
    # function on_button_clicked() defined above.
    button1.connect("clicked", on_button_clicked)

    # Creates labels with the sums
    sumrows = []
    sumcols = []

    for i in range(0, number_unknowns):
        sumrows.append(gtk.Label(str(row_sum[i])))
    
    for i in range(0, number_unknowns):
        sumcols.append(gtk.Label(str(column_sum[i])))
        sumcols[i].set_width_chars(4)
    

    # value, lower, upper, step_increment, page_increment, page_size
    # initializes the scales to choose answers from
    # first clear out the old list, so each scale[i] is a new widget
    while (scales):
        scales.pop()
    
    for i in range(0, number_unknowns):
        adj1 = gtk.Adjustment(0.0, 1.0, 20.0, 1.0, 1.0, 0.0)
        temp = gtk.HScale(adj1)
        scales.append(temp)
        scales[i].set_digits(0)
        scales[i].set_draw_value(True)
        scales[i].set_usize(75, 60)
    
        
# creates pack boxes, the formatting for the window
# note from elizabeth!! you can only add each widget ONCE!
# this means that when we are adding in images more than
# once, we actually have to create separate objects.
# so, if we want 4 apples to appear, we have to create
# 4 different objects that are the same thing!
# and also, we can't just say blah2 = blah and add blah2
# already tried it and it doesn't work.

    vbox1 = gtk.VBox(False, 10)
    boxes = []
    for i in range(0, number_unknowns):
        boxes.append(gtk.HBox(False, 20))

    for i in range(0, number_unknowns):
        boxes[i].pack_start(addBuffer(), False, False, 0)

    for i in range(0, number_unknowns):
        for j in range(0, number_unknowns):
            if grid[i][j] == 'a':
                boxes[i].pack_start(addApple(), False, False, 0)
            elif grid[i][j] == 'b':
                boxes[i].pack_start(addOrange(), False, False, 0)            
            elif grid[i][j] == 'c':
                boxes[i].pack_start(addBanana(), False, False, 0)          
            elif grid[i][j] == 'd':
                boxes[i].pack_start(addPlum(), False, False, 0)          
            elif grid[i][j] == 'e':
                boxes[i].pack_start(addPear(), False, False, 0)          
            elif grid[i][j] == 'f':
                boxes[i].pack_start(addMango(), False, False, 0)          
            elif grid[i][j] == 'g':
                boxes[i].pack_start(addStrawberry(), False, False, 0)
            elif grid[i][j] == 'h':
                boxes[i].pack_start(addKiwi(), False, False, 0)          
            elif grid[i][j] == 'i':
                boxes[i].pack_start(addWatermelon(), False, False, 0)

    # adds the sum of each of the rows
    for i in range(0, number_unknowns):
        boxes[i].pack_start(sumrows[i], False, False, 0)
        boxes[i].pack_start(addBuffer(), False, False, 0)
    
    # adds the image hboxes to the grid vbox
    for i in range(0, number_unknowns):
        vbox1.pack_start(boxes[i], False, False, 0)
    
    # adds the sum of each of the column
    hbox4 = gtk.HBox(False, 20)
    hbox4.pack_start(addBuffer(), False, False, 0)
    for i in range(0, number_unknowns):
        hbox4.pack_start(sumcols[i], False, False, 0)

    # adds the scales to an hbox
    hbox5 = gtk.HBox(False, 0)
    hbox5.pack_start(addBuffer(), False, False, 5)
    for i in range(0, number_unknowns):
        hbox5.pack_start(scales[i], False, False, 0)

    # adds the images to an hbox
    hbox6 = gtk.HBox(False, 25)
    hbox6.pack_start(addBuffer(), False, False, 0)
    for i in range(0, number_unknowns):
        if used_variables[i] == 'a':
            hbox6.pack_start(addApple(), False, False, 0)
        elif used_variables[i] == 'b':
            hbox6.pack_start(addOrange(), False, False, 0)            
        elif used_variables[i] == 'c':
            hbox6.pack_start(addBanana(), False, False, 0)          
        elif used_variables[i] == 'd':
            hbox6.pack_start(addPlum(), False, False, 0)          
        elif used_variables[i] == 'e':
            hbox6.pack_start(addPear(), False, False, 0)          
        elif used_variables[i] == 'f':
            hbox6.pack_start(addMango(), False, False, 0)          
        elif used_variables[i] == 'g':
            hbox6.pack_start(addStrawberry(), False, False, 0)
        elif used_variables[i] == 'h':
            hbox6.pack_start(addKiwi(), False, False, 0)          
        elif used_variables[i] == 'i':
            hbox6.pack_start(addWatermelon(), False, False, 0)

    # adds the check button
    hbox7 = gtk.HBox(False, 0)
    hbox7.pack_start(button1, False, False, 20)
    
    # adds everything to the main vbox
    vbox = gtk.VBox(False, 0)
    vbox.pack_start(menu_bar, False, False, 0)
    vbox.pack_start(vbox1, False, False, 15)
    vbox.pack_start(hbox4, False, False, 15)
    vbox.pack_start(hbox5, False, False, 15)
    vbox.pack_start(hbox6, False, False, 0)
    vbox.pack_start(hbox7, False, False, 20)

# This adds the box of pack boxes to the window.
# we have one vertical box in the window because
# we are not allowed to have more than 1 widget in
# the window. a widget is pretty much everything...
# image, button, etc. but you can put whatever you
# want and however much you want in a pack box,
# so it's okay.
    window.add(vbox)

# Show the window and the button
    window.show_all()
# Run the main loop, to process events such a key presses
# and mouse movements.
    gtk.main()

#end mainGame function

number_unknowns = 3

# scrolly bars for our little kiddies to choose their
# answers from
scales = []

# Dictionary that contains the variables as keys, mapped to the random numbers.
variable_dictionary = {}
used_variables = []


# starts out with a 5x5, change as you wish
mainGame(number_unknowns)

# stop music
pygame.mixer.quit()
